var defaultCountryId = 1;

var saveButton = $('a.save-button');
var profilePict = $('img.trainee-image');

var birthDateField = $('input[type="text"][placeholder="Birth date..."]');
var dateBaptizedField = $('input[type="text"][placeholder="Date baptized..."]');

birthDateField.datepicker( { format: 'mm/dd/yyyy' } );
birthDateField.datepicker('setValue', new Date());

dateBaptizedField.datepicker( { format: 'mm/dd/yyyy' } );
dateBaptizedField.datepicker('setValue', new Date());

var uidField = $('.data-input.form-control.username-field');
var pwdField1 = $('.data-input.form-control.user-password1');
var pwdField2 = $('.data-input.form-control.user-password2');

var accountInfoCollapse = $('a[data-toggle="collapse"][href="#account-info-pane"]');
var personalInfoCollapse = $('a[data-toggle="collapse"][href="#personal-info-pane"]');
var contactInfoCollapse = $('a[data-toggle="collapse"][href="#contact-info-pane"]');
var residenceInfoCollapse = $('a[data-toggle="collapse"][href="#residence-info-pane"]');
var educationInfoCollapse = $('a[data-toggle="collapse"][href="#education-info-pane"]');
var miscInfoCollapse = $('a[data-toggle="collapse"][href="#misc-info-pane"]');

var GenderModel = function(value, text) {

	var self = this;

	self.text = text;

	self.value = value;
};

var CountryModel = function(id, country) {

	var self = this;

	self.id = id;

	self.country = country;

};

var LocalityModel = function(id, locality) {

	var self = this;

	self.id = id;

	self.locality = locality;

};

var DistrictModel = function(id, locality, district) {

	var self = this;

	self.id = id;

	self.locality = locality;

	self.district = district;

};

var ResidentModel = function(info, countries, localities) {

	var self = this;

	self.id = info.Id;

	self.trainee = info.Trainee;

	self.validate = function() {
		try {
			if (self.country() <= 0) return false;
			if (self.unitNo().trim() == '') return false;
			if (self.street().trim() == '') return false;
			if (self.area().trim() == '') return false;
			if (self.locality() <= 0) return false;
		}
		catch (ex) {

		}

		return true;
	};

	self.isValid = function() {
		var validTrainee = true;

		try {
			validTrainee = self.trainee.isValid();
		}
		catch (ex) {

		}

		return validTrainee && self.validate();
	};

	self.unitNo =  ko.observable(info.UnitNo).extend( { modelUpdated : self, validator: { 'saveButton': saveButton, saveButtonEnable: function() { return self.isValid(); } } } );

	self.street = ko.observable(info.Street).extend( { modelUpdated : self, validator: { 'saveButton': saveButton, saveButtonEnable: function() { return self.isValid(); } } } );

	self.subdivision = ko.observable(info.Subdivision).extend( { modelUpdated : self } );

	self.area = ko.observable(info.Area).extend( { modelUpdated : self, validator: { 'saveButton': saveButton, saveButtonEnable: function() { return self.isValid(); } } } );

	self.countries = ko.observableArray(ko.utils.arrayMap(countries, function(country) {
		var model = new CountryModel(country.Id, country.Country);
		return model;
	}));

	self.country = ko.observable(info.CountryId).extend( { modelUpdated : self, validator: { mode: 'int', 'saveButton': saveButton, references: ko.toJS(self.countries), referenceKey: 'id', saveButtonEnable: function() { return self.isValid(); } } } )

	self._localities = localities;

	self.localities = ko.computed(function() {
		try {
			self.locality(0);
		}
		catch (ex) {

		}

		var l = self._localities;

		var dataSource = [];

		var selectedCountry = defaultCountryId;

		try {
			selectedCountry  = self.country();
		}
		catch(ex) {

		}

		$.each(l, function(index) {
			var locality = this;
			if (locality.CountryId == selectedCountry) dataSource.push( { id: locality.Id, locality: locality.Locality } );
		});

		return dataSource;
	});

	self.locality = ko.observable(info.LocalityId).extend( { modelUpdated : self, validator: { mode: 'int', 'saveButton': saveButton, references: self._localities, referenceKey: 'Id', saveButtonEnable: function() { return self.isValid(); } } } );

	self.RowState = 'unchanged';

};

var EducationModel = function(info, educationlevels) {

	var self = this;

	self.id = info.Id;

	self.trainee = info.Trainee;

	self.validate = function() {
		try {
			if (self.educationalDegree() <= 0) return false;
			if (self.school().trim() == '') return false;
			if (self.yearAttended() <= 0) return false;
			if (self.monthAttended() <= 0) return false;
		}
		catch (ex) {

		}

		return true;	
	};

	self.isValid = function() {
		var validTrainee = true;

		try {
			validTrainee = self.trainee.isValid();
		}
		catch (ex) {

		}

		return validTrainee && self.validate();
	};

	self.educationalDegrees = ko.observableArray(ko.utils.arrayMap(educationlevels, function(level) {
		var model = { id: level.Id, educationalDegree: level.EducationalDegree };
		return model;
	}));

	self.educationalDegree =  ko.observable(info.EducationalDegreeId).extend( { modelUpdated : self, validator: { mode: 'int', 'saveButton': saveButton, references: ko.toJS(self.educationalDegrees), referenceKey: 'id', saveButtonEnable: function() { return self.isValid(); } } } );

	self.school = ko.observable(info.School).extend( { modelUpdated : self, validator: { 'saveButton': saveButton, saveButtonEnable: function() { return self.isValid(); } } } );

	self.course = ko.observable(info.Course).extend( { modelUpdated : self } );

	self.years = ko.computed(function() {
		var dataSource = [];

		var yearGrad = 0;
		var yearAtt = 0;

		try {
			yearAtt = self.yearAttended();
			yearGrad = self.yearGraduated();	
		}
		catch (ex) {
			yearAtt = info.YearAttended;
			yearGrad = info.YearGraduated;	
		}

		var dob = new Date();

		try {
			dob = new Date(Date.parse(self.trainee.birthDate()));
		}
		catch (ex) {
			if (self.trainee != undefined) {
				if (self.trainee.birthDate != undefined) {
					try {
						dob = new Date(Date.parse(self.trainee.birthDate));
					}
					catch (x) {

					}
				}
			}
		}

		try {
			var now = new Date();

			var attExists = false;
			var gradExists = false;

			for (i = dob.getFullYear() + 1; i <= now.getFullYear(); i++) {
				if (yearAtt == i) attExists = true;
				if (gradExists == i) gradExists = true;

				dataSource.push(i);
			}

			if (gradExists) self.yearGraduated(yearGrad);
			else self.yearGraduated(0);

			if (attExists) self.yearAttended(yearAtt);
			else self.yearAttended(0);
		}
		catch (ex) {

		}

		return dataSource;
	});
   
	self.yearAttended = ko.observable(info.YearAttended).extend( { modelUpdated : self, validator: { mode: 'int', 'saveButton': saveButton, references: self.years(), saveButtonEnable: function() { return self.isValid(); } } } );

	self.months = null;

	self.initializeMonths = function() {
		var m = [];

		var months = [ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' ];
		for (i = 0; i < months.length; i++) {
			m.push({ id: i + 1, month: months[i] });
		}

		self.months = ko.observableArray(m);
	};

	self.initializeMonths();

	self.monthAttended = ko.observable(info.MonthAttended).extend( { modelUpdated : self, validator: { mode: 'int', 'saveButton': saveButton, references: ko.toJS(self.months), referenceKey: 'id', saveButtonEnable: function() { return self.isValid(); } } } );

	self.yearGraduated = ko.observable(info.YearGraduated).extend( { modelUpdated : self } );

	self.monthGraduated = ko.observable(info.MonthGraduated).extend( { modelUpdated : self } );

	self.RowState = 'unchanged';

};

ko.extenders.genderUpdated = function(target, model) {
    
    target.subscribe(function(newValue) {
    	var gender = 'bro';

    	try {
    		var value = target();

    		gender = (value.trim().toLowerCase() == 's'? 'sis' : 'bro'); 
    	}
    	catch (ex) {
    		console.error(ex);
    	}

    	var imageSrc = app.baseUrl() + 'img/' + gender + '.png';
    	
    	if (model != undefined) {
    		if (model != null) {
    			if (model.image != undefined) {
    				var counterImage = app.baseUrl() + 'img/' + (gender.trim() == 'sis'? 'bro' : 'sis') + '.png';
    				var image = counterImage;

    				try {
    					image = model.image();
    				}
    				catch (ex) {
    					console.error(ex);
    				}

    				if (image == counterImage) {
    					try {
    						console.info(imageSrc);
    						model.image(imageSrc);
    					}
    					catch (ex) {
    						console.error(ex);
    					}
    				}
    			}
    		}
    	}
    });

    return target;
};

ko.extenders.accountInfoUpdated = function(target, trainee) {

	target.subscribe(function(newValue) {
		if (trainee != undefined &&
			trainee != null) {
			try {
				var uid = trainee.userName();
				var pwd1 = trainee.password1();
				var pwd2 = trainee.password2();

				if (trainee.originalUserName.trim() == '') {
					if (uid.trim() != '' &&
						(pwd1.trim() == '' || pwd2.trim() == '')) {
						var formGroupDiv1 = pwdField1.closest('div.form-group');
						var formGroupDiv2 = pwdField2.closest('div.form-group');

						if (!formGroupDiv1.hasClass('has-error')) formGroupDiv1.addClass('has-error');
						if (!formGroupDiv2.hasClass('has-error')) formGroupDiv2.addClass('has-error');

						return;
					}

					if ((pwd1.trim() != '' || pwd2.trim() != '') &&
						uid.trim() == '') {
						var formGroupDiv = uidField.closest('div.form-group');
						if (!formGroupDiv.hasClass('has-error')) formGroupDiv.addClass('has-error');
						return ;
					}
					
					if (pwd1.trim() === pwd2.trim()) {
						var formGroupDiv1 = pwdField1.closest('div.form-group');
						var formGroupDiv2 = pwdField2.closest('div.form-group');
						
						formGroupDiv1.removeClass('has-error');
						formGroupDiv2.removeClass('has-error');
						return;					
					}
				}
				else {
					if (pwd1.trim() === pwd2.trim() &&
						pwd1.trim() != '' &&
						pwd2.trim() != '') {
						var formGroupDiv1 = pwdField1.closest('div.form-group');
						var formGroupDiv2 = pwdField2.closest('div.form-group');
						
						formGroupDiv1.removeClass('has-error');
						formGroupDiv2.removeClass('has-error');
						return;					
					}
				}
			}
			catch (ex) {

			}
		}
	});

};

var TraineeModel = function(trainee, countries, localities, districts, educationlevels) {

	var self = this;

	self.firstName = trainee.FirstName;

	self.lastName = trainee.LastName;

	self.birthDate = trainee.BirthDate;

	self.genders = null;

	self.initializeGenders = function() {
		var bro = new GenderModel('B', 'Brother');
		var sis = new GenderModel('S', 'Sister');
		
		var genders = [];
		genders.push(bro);
		genders.push(sis);

		self.genders =  ko.observableArray(genders); 
	};

	self.initializeGenders();

	self.gender = trainee.Gender;

	self.statusList = [ 'Single', 'Married', 'Divorced', 'Widowed' ];

	self.maritalStatus = trainee.MaritalStatus;

	self._countries = countries;

	self.countries = null;

	self.initializeCountries = function() {
		var c = [];

		for (i = 0; i < self._countries.length; i++) {
			var country = countries[i];
			var model = new CountryModel(country.Id, country.Country);
			c.push(model);
		}

		self.countries = ko.observableArray(c);
	};

	self.initializeCountries();

	self.nationality = trainee.NationalityId;

	self._localities = localities;

	self.localities = null;

	self.initializeLocalities = function() {
		var l = [];

		for (i = 0; i < self._localities.length; i++) {
			var locality = localities[i];
			var model = new LocalityModel(locality.Id, locality.Locality);
			l.push(model);
		}

		self.localities = ko.observableArray(l);
	};

	self.initializeLocalities();

	self.locality = trainee.LocalityId;

	self._districts = districts;

	self.districts = [];

	self.district = trainee.DistrictId;

	self.email = trainee.Email;

	self.dateBaptized = trainee.DateBaptized;

	self.baptismalLocality = trainee.BaptismalLocalityId;

	self.addressIds = [];

	self.addresses = ko.observableArray(ko.utils.arrayMap(trainee.Addresses, function(address) {
		self.addressIds.push(address.Id);

		address.Trainee = self;
		var model = new ResidentModel(address, self._countries, self._localities);
		return model;
	}));

	self.educationIds = [];

	self._educationLevels = educationlevels;

	self.educations = ko.observableArray(ko.utils.arrayMap(trainee.Educations, function(education) {
		self.educationIds.push(education.Id);

		education.Trainee = self;
		var model = new EducationModel(education, self._educationLevels);
		return model;
	}));

	self.isValid = function() {
		try {
			if (self.password1() !== self.password2()) return false;

			var pwd = self.password1();
			var uid = self.userName();

			if (self.originalUserName.trim() != '' &&
				(uid.trim() == '' || pwd.trim() == '')) return false;

			if (pwd.trim() != '' &&
				uid.trim() == '') return false;

			if (uid.trim() != '' &&
				pwd.trim() == '') return false;

			if (self.firstName().trim() == '') return false;

			if (self.lastName().trim() == '') return false;

			if (self.gender().toLowerCase().trim() != 'b' &&
				self.gender().toLowerCase().trim() != 's') return false;

			var matchedStatus = false;

			for (i = 0; i < self.statusList.length; i++) {
				var status = self.statusList[i];
				if (status.toLowerCase().trim() == self.maritalStatus().toLowerCase().trim()) {
					matchedStatus = true; break;
				}
			}

			if (!matchedStatus) return false;

			if (self.nationality() <= 0) return false;

			if (self.locality() <= 0) return false;

			if (self.district() <= 0) return false;

			if (!self.email().trim().isEmail()) return false;

			if (self.baptismalLocality() <= 0) return false;

			var dob = Date.parse(self.birthDate());
			var baptismalDate = Date.parse(self.dateBaptized());

			if (baptismalDate < dob) return false; 	
		}
		catch (ex) {

		}
	
		var addresses = [];

		try {
			addresses = ko.toJS(self.addresses);
		}
		catch (ex) {
		
		}

		if (addresses.length <= 0) return false;
		else {
			for (i = 0; i < addresses.length; i++) {
				var address = addresses[i];
				if (!address.validate()) return false;
			}
		}

		var educations = [];

		try {
			educations = ko.toJS(self.educations);
		}
		catch (ex) {

		}

		if (educations.length > 0) {
			for (i = 0; i < educations.length; i++) {
				var education = educations[i];
				if (!education.validate()) return false;
			}
		}

		return true;
	};

	self.id = trainee.Id;

	self.originalUserName = trainee.Username;

	self.userName = ko.observable(trainee.Username).extend( { modelUpdated : self, accountInfoUpdated: self, validator: { 'mode': (self.originalUserName.trim() == ''? 'string/empty-allowed' : 'string'), 'saveButton': saveButton, saveButtonEnable: function() { return self.isValid(); } } } );

	self.persistingPasswordValue1 = function() {
		try {
			return self.password2(); 
		}
		catch (ex) {
			return null;
		}
	};

	self.originalPassword = trainee.Password;

	self.password1 = ko.observable(trainee.Password).extend( { modelUpdated : self, accountInfoUpdated: self, validator: { 'mode': (self.originalUserName.trim() == ''? 'password/empty-allowed' : 'password'), persistingValue : self.persistingPasswordValue1, 'saveButton': saveButton, saveButtonEnable: function() { return self.isValid(); } } } );

	self.persistingPasswordValue2 = function() {
		try {
			return self.password1();
		}
		catch (ex) {
			return null;
		}
	};

	self.password2 = ko.observable(trainee.Password).extend( { modelUpdated : self, accountInfoUpdated: self, validator: { 'mode': (self.originalUserName.trim() == ''? 'password/empty-allowed' : 'password'), persistingValue : self.persistingPasswordValue2, 'saveButton': saveButton, saveButtonEnable: function() { return self.isValid(); } } } );

	self.firstName = ko.observable(trainee.FirstName).extend( { modelUpdated : self, validator: { 'saveButton': saveButton, saveButtonEnable: function() { return self.isValid(); } } } );

	self.middleName = ko.observable(trainee.MiddleName).extend( { modelUpdated : self } );

	self.lastName = ko.observable(trainee.LastName).extend( { modelUpdated : self, validator: { 'saveButton': saveButton, saveButtonEnable: function() { return self.isValid(); } } } );

	self.birthDate = ko.observable(trainee.BirthDate).extend( { modelUpdated : self, validator: { mode: 'date', 'saveButton': saveButton, saveButtonEnable: function() { return self.isValid(); } } } );

	self.gender = ko.observable(trainee.Gender).extend( { modelUpdated : self, genderUpdated: self, validator: { mode: 'int', 'saveButton': saveButton, references: ko.toJS(self.genders), referenceKey: 'value', saveButtonEnable: function() { return self.isValid(); } } } );

	self.maritalStatus = ko.observable(trainee.MaritalStatus).extend( { modelUpdated : self, validator: { 'saveButton': saveButton, references: self.statusList, saveButtonEnable: function() { return self.isValid(); } } } );

	self.nationality = ko.observable(trainee.NationalityId).extend( { modelUpdated : self, validator: { mode: 'int', 'saveButton': saveButton, references: ko.toJS(self.countries), referenceKey: 'id', saveButtonEnable: function() { return self.isValid(); } } } );

	self.locality = ko.observable(trainee.LocalityId).extend( { modelUpdated : self, validator: { mode: 'int', 'saveButton': saveButton, references: ko.toJS(self.localities), referenceKey: 'id', saveButtonEnable: function() { return self.isValid(); } } } );

	self.districts = ko.computed(function() {
		try {
			self.district('0');
		}
		catch (ex) {

		}
		
		var d = self._districts;
		var dataSource = [];

		var selectedLocality = 0;

		try {
			selectedLocality = self.locality();
		}
		catch (ex) {
			selectedLocality = self.locality;
		}

		$.each(d, function(index) {
			var district = this;
			if (district.LocalityId == selectedLocality) dataSource.push(new DistrictModel(district.Id, district.LocalityId, district.District));
		});

		return dataSource;
	});

	self.district = ko.observable(trainee.DistrictId).extend( { modelUpdated : self, validator: { mode: 'int', 'saveButton': saveButton, references: self._districts, referenceKey: 'Id', saveButtonEnable: function() { return self.isValid(); } } } );

	self.phoneNo = ko.observable(trainee.PhoneNo).extend( { modelUpdated : self } );

	self.mobileNo = ko.observable(trainee.MobileNo).extend( { modelUpdated : self } );

	self.email = ko.observable(trainee.Email).extend( { modelUpdated : self, validator: { mode: 'email', 'saveButton': saveButton, saveButtonEnable: function() { return self.isValid(); } } } );

	self.passportNo = ko.observable(trainee.PassportNo).extend( { modelUpdated : self } );

	self.dateBaptized = ko.observable(trainee.DateBaptized).extend( { modelUpdated : self, validator: { mode: 'date', 'saveButton': saveButton, saveButtonEnable: function() { return self.isValid(); } } } );

	self.baptismalLocality = ko.observable(trainee.BaptismalLocalityId).extend( { modelUpdated : self, validator: { mode: 'int', 'saveButton': saveButton, references: ko.toJS(self.localities), referenceKey: 'id', saveButtonEnable: function() { return self.isValid(); } } } );

	self.image = ko.observable(trainee.Image);

	self.age = ko.computed(function() {
		var dob = new Date();

		try {
			dob = Date.parse(self.birthDate());
		}
		catch (ex) {

		}

		var now = new Date();
		return now.diff(dob, 'year');
	});

	self.RowState = (trainee.Id <= 0? 'added' : 'unchanged');

	self.acceptChanges = function(viewUpdates) {
		if (viewUpdates != undefined) {
			if (self.RowState == 'added') {
				if (viewUpdates.trainee != undefined) {
					if (viewUpdates.trainee.GeneratedId != undefined) self.id = viewUpdates.trainee.GeneratedId;
				}	
			}

			if (viewUpdates.addresses != undefined) {
				ko.utils.arrayForEach(self.addresses(), function(address) {
					address.RowState = 'unchanged';

					for (i = 0; i < viewUpdates.addresses.length; i++) {
						var viewUpdate = viewUpdates.addresses[i];
						if (address.id == viewUpdate.Id) {
							address.id = viewUpdate.GeneratedId;
							break;
						}
					}
				});
			}

			if (viewUpdates.educations != undefined) {
				ko.utils.arrayForEach(self.educations(), function(education) {
					education.RowState = 'unchanged';

					for (i = 0; i < viewUpdates.educations.length; i++) {
						var viewUpdate = viewUpdates.educations[i];
						if (education.id == viewUpdate.Id) {
							education.id = viewUpdate.GeneratedId;
							break;
						}
					}
				});	
			}
		}

		self.RowState = 'unchanged';
	};

	self.deletedAddresses = [];

	self.deletedEducations = [];

	self.addAddress = function() {
		var id = 1;

		if (self.addressIds.length > 0) {
			var max = Math.max.apply(Math, self.addressIds);
			id = max + 1;
		}

		self.addressIds.push(id);

		var info = {
			Id: id,
			UnitNo: '',
			Street: '',
			Subdivision: '',
			Area: '',
			CountryId: defaultCountryId,
			LocalityId: 0,
			Trainee: self
		};

		var model = new ResidentModel(info, self._countries, self._localities);
		model.RowState = 'added';

		self.addresses.push(model);

		setRemoveTraineeToolTips();
	};

	self.addEducation = function() {
		var id = 1;

		if (self.educationIds.length > 0) {
			var max = Math.max.apply(Math, self.educationIds);
			id = max + 1;
		}

		self.educationIds.push(id);

		var now = new Date();

		var info = {
			Id: id,
			EducationalDegreeId: 0,
			School: '',
			Course: '',
			YearAttended: 0,
			MonthAttended: 6,
			YearGraduated: 0,
			MonthGraduated: 3,
			Trainee: self
		};

		var model = new EducationModel(info, self._educationLevels);
		model.RowState = 'added';

		self.educations.push(model);

		setRemoveTraineeToolTips();
	};

	self.browseImage = function() {
		var rowState = 'added';

		if (self.RowState != undefined) {
			if (self.RowState != null) rowState = self.RowState;
		}

		if (rowState != 'added') {
			openFileDialog.show({
				filter: 'image/*',
				onFileNameSelected: function(file) {
					if (file == undefined) {
						profilePict.removeClass('disabled'); return;
					}

					if (profilePict.hasClass('disabled')) return;
					else profilePict.addClass('disabled');

					var limit = 1024 * 1024;
					if (file.size > limit) {
						warningGritter({
							title: 'Image Upload',
							text: 'The specified image is too huge. Please specify an image with a maximum size of 1MB.'
						});
					}
					else {
						var reader = new FileReader();
					    reader.onload = function(e) {
					    	var uri = e.target.result;

					    	var updates = { Id: self.id, Image: uri };
					    	
							var container = profilePict.closest('div.col-md-2');
					    	app.loader({ 'container': container });

					    	$.ajax({
							    type: 'POST',
							    url: app.baseUrl() + 'index.php/references/updateProfilePict',
							    data: { 'data' : JSON.stringify(updates) },
							    dataType: 'json'
							}).done(function(response) {
								var saved = true;
								var message = 'Unable to update the profile image. Please try again.';

								if (response.saved != undefined) {
									if (response.saved != null) saved = response.saved;
								}

								if (response.message != undefined) {
									if (response.message != null) message = response.message;
								}

								if (saved) profilePict.attr('src', uri);
								else {
									warningGritter({
										title: 'Update Profile Picture',
										text: message
									});
								}
							}).fail(function(response) {
								try {
									console.error(response);
								}
								catch (ex) {

								}

								errorGritter({
									title: 'Oooops',
									text: 'Something went wrong while trying to update the profile image.'
								});
							}).always(function() {
								app.loader('hide');
								profilePict.removeClass('disabled');
							});
					    };

					    reader.readAsDataURL(file);
					}
				}
			});
		}
	}

	self.getChanges = function() {
		var changes = { };

		var dob = new Date();

		try {
			dob = new Date(Date.parse(self.birthDate()));
		}
		catch (ex) {

		}

		var baptismalDate = new Date();

		try {
			baptismalDate = new Date(Date.parse(self.dateBaptized()));
		}
		catch (ex) {

		}

		changes.trainee = {
			Id: self.id,
			Username: self.userName(),
			Password: self.password1(),
			FirstName: self.firstName(),
			MiddleName: self.middleName(),
			LastName: self.lastName(),
			BirthDate: dob.toSqlDateString(),
			Gender: self.gender(),
			MaritalStatus: self.maritalStatus(),
			NationalityId: self.nationality(),
			LocalityId: self.locality(),
			DistrictId: self.district(),
			PhoneNo: self.phoneNo(),
			MobileNo: self.mobileNo(),
			Email: self.email(),
			PassportNo: self.passportNo(),
			DateBaptized: baptismalDate.toSqlDateString(),
			BaptismalLocalityId: self.baptismalLocality(),
			RowState: self.RowState
		};

		var addresses = ko.toJS(self.addresses);
		changes.addresses = [];

		for (i = 0; i < addresses.length; i++) {
			var address = addresses[i];
			if (address.RowState == 'added' ||
				address.RowState == 'modified') changes.addresses.push({
													Id: address.id,
													UnitNo: address.unitNo,
													Street: address.street,
													Subdivision: address.subdivision,
													Area: address.area,
													LocalityId: address.locality,
													CountryId: address.country,
													RowState: address.RowState
												});
		}

		for (i = 0; i < self.deletedAddresses.length; i++) {
			var address = self.deletedAddresses[i];
			changes.addresses.push({
				Id: address.id,
				UnitNo: '',
				Street: '',
				Subdivision: '',
				Area: '',
				LocalityId: 0,
				CountryId: 0,
				RowState: 'deleted'
			});
		}

		var educations = ko.toJS(self.educations);
		changes.educations = [];

		for (i = 0; i < educations.length; i++) {
			var education = educations[i];
			if (education.RowState == 'added' ||
				education.RowState == 'modified') changes.educations.push({
													Id: education.id,
													EducationDegreeId: education.educationalDegree,
													School: education.school,
													Course: education.course,
													YearAttended: education.yearAttended,
													MonthAttended: education.monthAttended,
													YearGraduated: education.yearGraduated,
													MonthGraduated: education.monthGraduated,
													RowState: education.RowState
												  });	
		}

		for (i = 0; i < self.deletedEducations.length; i++) {
			var education = self.deletedEducations[i];
			changes.educations.push({
				Id: education.id,
				EducationDegreeId: 0,
				School: '',
				Course: '',
				YearAttended: 0,
				MonthAttended: 0,
				YearGraduated: 0,
				MonthGraduated: 0,
				RowState: 'deleted'
			});	
		}

		return changes;
	};

	self.goToList = function() {
		var goToListButton = $('a[href="#trainee-list"]');
		if (goToListButton.hasClass('disabled')) return;
		else goToListButton.addClass('disabled');

		$.post(app.baseUrl() + 'index.php/home/setTraineeId', {
			id: 0
		}).done(function(response) {
			$.post(app.baseUrl() + 'index.php/home/setView', {
				view: 'trainees'
			}).done(function(data) {
				if (data == 'trainees') window.location.replace(app.baseUrl());
			}).fail(function(data) {
				try {
					console.error(data);
				}
				catch (ex) {

				}

			}).always(function() {
				goToListButton.removeClass('disabled');				
			});
		}).fail(function(response) {
			try {
				console.error(response);
			}
			catch (ex) {

			}

			goToListButton.removeClass('disabled');
		}).always(function() {

		});
	};

	self.imageHoverIn = function() {
		var message = '';

		if (self.RowState == 'added') message = 'Trainee image can be updated once information has been saved.';
		else message = 'Click to update trainee image.';

		profilePict.tooltip('destroy');

		profilePict.tooltip({
			'title' : message,
			'container' : 'body',
			'placement' : 'bottom auto'
		});
	};

	self.imageHoverIn();

	self.removeAddress = function(address) {
		if (address.RowState != 'added') {
			address.RowState = 'deleted';
			self.deletedAddresses.push(address);
		}

		setRemoveTraineeToolTips();

		self.addresses.remove(address);

		if (self.isValid())  saveButton.removeClass('disabled');
		else {
			if (!saveButton.hasClass('disabled')) saveButton.addClass('disabled');
		}
	};

	self.removeEducation = function(education) {
		if (education.RowState != 'added') {
			education.RowState = 'deleted';
			self.deletedEducations.push(education);
		}

		setRemoveTraineeToolTips();

		self.educations.remove(education);
		
		if (self.isValid())  saveButton.removeClass('disabled');
		else {
			if (!saveButton.hasClass('disabled')) saveButton.addClass('disabled');
		}	
	};

	self.save = function() {
		if (saveButton.hasClass('disabled')) return;
		else saveButton.addClass('disabled');

		saveButton.button('loading');

		var withUpdates = false;
		var updates = self.getChanges();
		
		try {
			console.info(updates);
		}
		catch (ex) {

		}

		if (updates != null) {
			if (updates.trainee != undefined) {
				if (updates.trainee.RowState != 'unchanged') withUpdates = true;
			}

			if (!withUpdates) {
				if (updates.addresses != undefined) {
					if (updates.addresses.length > 0) withUpdates = true;
				}
			}

			if (!withUpdates) {
				if (updates.educations != undefined) {
					if (updates.educations.length > 0) withUpdates = true;
				}
			}
		}

		if (withUpdates) {
			$.ajax({
			    type: 'POST',
			    url: app.baseUrl() + 'index.php/references/update',
			    data: { 'data' : JSON.stringify(updates) },
			    dataType: 'json'
			}).done(function(response) {
				try {
					console.info(response);
				}
				catch (ex) {

				}

				if (response.saved != undefined) {
					if (response.saved) {
						if (response.viewUpdates != undefined) self.acceptChanges(response.viewUpdates);	

						infoGritter({
							title: 'Record Update',
							text: 'Applied updates has been saved.'
						});		
					}
					else {
						var message = 'Applied updates were not saved into the database.';

						if (response.message != undefined &&
							response.message != null) {
							if (response.message.trim() != '') message = response.message;
						}

						warningGritter({
							title: 'Record Update',
							text: message
						});				
					}
				}
				
				
			}).fail(function(response) {
				try {
					console.error(response);
				}
				catch (ex) {

				}

				errorGritter({
					title: 'Oooops',
					text: 'Something went wrong while applying the updates into the server.'
				});
			}).always(function() {
				saveButton.removeClass('disabled');
				saveButton.button('reset');
			});
		}
		else {
			saveButton.removeClass('disabled');
			saveButton.button('reset');
		}
	};
	
};

var setRemoveTraineeToolTips = function() {
	unsetRemoveTraineeToolTips();
	var removeLinks = $('a.remove-record');
	removeLinks.tooltip( { 
			'title' : 'Remove current line-item from the list.',
			'trigger' : 'hover',
			'container' : 'body' 
		} 
	);
};

var unsetRemoveTraineeToolTips = function() {
	var removeLinks = $('a.remove-record');
	removeLinks.tooltip('destroy');
};

$(document).ready(function() {	
	var infoSection = $('.ninja.trainee-info');
	var traineeInfoData = infoSection.find('.trainee-info-section').text();
	var countriesData = infoSection.find('.country-section').text();
	var localitiesData = infoSection.find('.locality-section').text();
	var districtsData = infoSection.find('.district-section').text();
	var educationalLevelsData = infoSection.find('.educational-level-section').text();

	var traineeInfo = null;
	var countries = null;
	var localities = null;
	var districts = null;
	var educationalLevels = null;

	try {
		traineeInfo = JSON.parse(traineeInfoData);
		countries = JSON.parse(countriesData);
		localities = JSON.parse(localitiesData);
		districts = JSON.parse(districtsData);
		educationalLevels = JSON.parse(educationalLevelsData);
	}
	catch (ex) {

	}

	infoSection.remove();

	model = new TraineeModel(traineeInfo, countries, localities, districts, educationalLevels);
	ko.applyBindings(model);

	try {
		var dob = Date.parse(birthDateField.val());
		birthDateField.datepicker('setValue', dob);
	}
	catch (ex) {

	}

	try {
		var dateBaptized = Date.parse(dateBaptizedField.val());
		dateBaptizedField.datepicker('setValue', dateBaptized);
	}
	catch (ex) {

	}
	
	birthDateField.unbind('changeDate');
	birthDateField.on('changeDate', function(e) {
		var ageField = $('.data-input.form-control[placeholder="Age..."]');
		try {
			var dob = Date.parse(birthDateField.val());
			var now = new Date();
			ageField.val(now.diff(dob, 'year'));
			model.birthDate(birthDateField.val());
		}
		catch (ex) {

		}
	});

	dateBaptizedField.unbind('changeDate');
	dateBaptizedField.on('changeDate', function(e) {
		try {
			model.dateBaptized(dateBaptizedField.val());
		}
		catch(ex) {

		}
	});

	var traineeId = 0;

	if (traineeInfo != null) {
		if (traineeInfo.Id != undefined) traineeId = traineeInfo.Id;
	}

	if (traineeId <= 0) model.addAddress();

	educationInfoCollapse.collapse({ toggle: true });

	accountInfoCollapse.collapse({ toggle: (traineeId > 0) });
	contactInfoCollapse.collapse({ toggle: (traineeId > 0) });
	residenceInfoCollapse.collapse({ toggle: (traineeId > 0) });
	miscInfoCollapse.collapse({ toggle: (traineeId > 0) });

	setRemoveTraineeToolTips();

	var firstNameField = $('input.data-input.form-control[placeholder="Given name..."]');
	firstNameField.focus();

	var collapseSections = $('.panel-title').find('a[data-toggle="collapse"]');

	collapseSections.tooltip({
		'title' : 'Expand or collapse section.',
		'trigger' : 'hover',
		'container' : 'body',
		'placement': 'left auto'
	});
});